package com.neusoft.neuiotms.dcom.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.notice.constant.NoticeConsts;
import com.neusoft.bizcore.notice.notification.dto.NoticeDingDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordDTO;
import com.neusoft.bizcore.notice.notification.dto.NoticeRecordSystemDTO;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.bizcore.web.utils.JsonUtils;
import com.neusoft.neuiotms.dcom.bean.ProjectUserBean;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.converter.QuestionnaireConverter;
import com.neusoft.neuiotms.dcom.dto.OperationGroupDTO;
import com.neusoft.neuiotms.dcom.dto.QuestionnaireDTO;
import com.neusoft.neuiotms.dcom.model.Questionnaire;
import com.neusoft.neuiotms.dcom.model.enums.QuestionnaireScope;
import com.neusoft.neuiotms.dcom.repository.QuestionnaireFeedbackRepository;
import com.neusoft.neuiotms.dcom.repository.QuestionnaireRepository;
import com.neusoft.neuiotms.dcom.service.InstitutionsService;
import com.neusoft.neuiotms.dcom.service.OperationGroupService;
import com.neusoft.neuiotms.dcom.service.QuestionnaireService;
import com.neusoft.neuiotms.micro.auth.AuthMicroService;
import com.neusoft.neuiotms.micro.notice.NoticeMicroService;

@Service
public class QuestionnaireServiceImpl implements QuestionnaireService {

    @Autowired
    private QuestionnaireRepository questionnaireRepository;
    @Autowired
    private QuestionnaireConverter questionnaireConverter;
    @Autowired
    private NoticeMicroService noticeMicroService;
    @Autowired
    private OperationGroupService operationGroupService;
    @Autowired
    private InstitutionsService institutionsService;
    @Autowired
    private QuestionnaireFeedbackRepository questionnaireFeedbackRepository;
    @Autowired
    private AuthMicroService authMicroService;

    @Override
    public List<QuestionnaireDTO> index(final Searchable searchable, final UserBean userBean) {
        final ProjectUserBean info = this.institutionsService.getMyInstitutions(userBean);

        final boolean isWorker =
                userBean.getRoles().stream().filter(it -> it.getRole().equals(DCOMConstants.ROLE_WORKER)).findAny()
                        .isPresent();
        if (isWorker) {
            searchable.put("groupCode", info.getGroupCode());
        }
        final boolean isZongjianOrWorkerGroupLeader =
                userBean.getRoles().stream()
                        .filter(it -> it.getRole().equals(DCOMConstants.ROLE_WORKER_GROUP_LEADER)
                                || it.getRole().equals(DCOMConstants.ROLE_ZONGJIAN))
                        .findAny()
                        .isPresent();
        if ((isWorker || isZongjianOrWorkerGroupLeader) && searchable.hasKey("todo")) {
            searchable.put("closedAt", (new Date()).getTime());
            searchable.put("published", true);
        }
        List<Questionnaire> list = this.questionnaireRepository.index(searchable);

        if ((isWorker || isZongjianOrWorkerGroupLeader) && searchable.hasKey("todo")) {
            list = list.stream()
                    .filter(q -> {
                        final long count = this.questionnaireFeedbackRepository
                                .countByUsernameAndQuestionnaire_IdAndSubmitted(userBean.getUsername(), q.getId(),
                                        true);
                        return count == 0;
                    })
                    .collect(Collectors.toList());
        }

        return this.questionnaireConverter.toListDTO(list);
    }

    @Override
    public Page<QuestionnaireDTO> search(final Pageable pageable, final Searchable searchable,
            final UserBean userBean) {
        final ProjectUserBean info = this.institutionsService.getMyInstitutions(userBean);
        searchable.put("groupCode", info.getGroupCode());
        if (userBean.getRoles().stream().filter(it -> it.getRole().equals(DCOMConstants.ROLE_WORKER)).findAny()
                .isPresent()) {
            searchable.put("closedAt", (new Date()).getTime());
            searchable.put("published", true);
        }
        final Page<Questionnaire> page = this.questionnaireRepository.search(pageable, searchable);
        return this.questionnaireConverter.toPageDTO(page);
    }

    @Override
    public QuestionnaireDTO create(final QuestionnaireDTO dto) {
        Questionnaire model = this.questionnaireConverter.toModel(dto);
        model = this.questionnaireRepository.save(model);
        return this.questionnaireConverter.toDTO(model);
    }

    @Override
    public QuestionnaireDTO update(final Long id, final QuestionnaireDTO dto) {
        Questionnaire model = this.questionnaireConverter.toModel(dto);
        model = this.questionnaireRepository.save(model);
        return this.questionnaireConverter.toDTO(model);
    }

    @Override
    public QuestionnaireDTO details(final Long id) {
        Questionnaire model = null;
        try {
            model = this.questionnaireRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException("实体不存在");
        }

        return this.questionnaireConverter.toDTO(model);
    }

    @Override
    public void delete(final Long id) {
        this.questionnaireRepository.deleteById(id);

    }

    @Override
    public boolean publish(final Long id) {
        Questionnaire questionnaire = null;
        try {
            questionnaire = this.questionnaireRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException("实体不存在");
        }
        questionnaire.setPublished(true);
        questionnaire.setPublishAt(new Date());
        this.questionnaireRepository.save(questionnaire);

        final NoticeRecordDTO notice = new NoticeRecordDTO();
        notice.setCreateTime(new Date());
        notice.setAppCode("dcom");
        notice.setType(Lists.newArrayList(NoticeConsts.INFORM_TYPE_NOTICE, NoticeConsts.INFORM_TYPE_DINGDING));
        notice.setTitle(questionnaire.getType().getValue());

        // 一线工程师工作总结发送站内通知和钉钉共享通知
        if (QuestionnaireScope.WORKER.equals(questionnaire.getScope())) {
            final OperationGroupDTO groupInfo = this.operationGroupService.detail(questionnaire.getGroupCode());
            final List<String> users = Lists.newArrayList();
            groupInfo.getInstitutionsList().forEach(inst -> {
                users.addAll(inst.getResidents().stream().map(re -> re.getUsername()).collect(Collectors.toList()));
            });
            this.buildNoticeToWorker(notice, questionnaire.getType().getValue(), questionnaire.getTitle(), users);
            this.noticeMicroService.createNotification(JsonUtils.pojoToJson(notice));
        } else {

            // 一线组长工作总结发送站内通知和钉钉普通文本通知；
            final Map<String, Object> queryMap = Maps.newHashMap();
            final List<String> workGroupLeaderArray = Lists.newArrayList();
            queryMap.put("s_roleCode", DCOMConstants.ROLE_WORKER_GROUP_LEADER);
            final List<Map<String, Object>> leaderList = this.authMicroService.userIndex(queryMap).getData();
            leaderList.stream().forEach(e -> {
                workGroupLeaderArray.add(e.get("username").toString());
            });
            this.buildNoticeToWorkerGroupLeader(notice, questionnaire.getType().getValue(), questionnaire.getTitle(),
                    workGroupLeaderArray);
            this.noticeMicroService.createNotification(JsonUtils.pojoToJson(notice));

            // 主管发送站内通知
            queryMap.clear();
            notice.setSystem(null);
            notice.setDing(null);
            final List<String> zongjianArray = Lists.newArrayList();
            queryMap.put("s_roleCode", DCOMConstants.ROLE_ZONGJIAN);
            final List<Map<String, Object>> zongjianList = this.authMicroService.userIndex(queryMap).getData();
            zongjianList.stream().forEach(e -> {
                zongjianArray.add(e.get("username").toString());
            });
            this.buildNoticeToZongjian(notice, questionnaire.getType().getValue(), questionnaire.getTitle(),
                    zongjianArray);

            this.noticeMicroService.createNotification(JsonUtils.pojoToJson(notice));
        }

        return true;
    }

    /**
     * 构造一线工程师通知消息体
     *
     * @param type
     * @param content
     * @param users
     * @return
     */
    private void buildNoticeToWorker(NoticeRecordDTO notice, String type, String content, List<String> users) {
        this.buildWebNotice(notice, type, content, users);
        this.buildDingLinkNotice(notice, type, content, users);
    }

    private void buildNoticeToWorkerGroupLeader(NoticeRecordDTO notice, String type, String content,
            List<String> users) {
        this.buildWebNotice(notice, type, content, users);
        this.buildDingTextNotice(notice, type, content, users);
    }

    private void buildNoticeToZongjian(NoticeRecordDTO notice, String type, String content,
            List<String> users) {
        this.buildWebNotice(notice, type, content, users);
    }

    /**
     * 添加页面通知
     *
     * @param type
     * @param content
     * @param users
     * @return
     */
    private void buildWebNotice(NoticeRecordDTO notice, String type, String content, List<String> users) {
        final NoticeRecordSystemDTO toSystem = new NoticeRecordSystemDTO();
        toSystem.setNoticeType(type);
        toSystem.setUsers(users);
        toSystem.setContent(content);
        notice.setSystem(toSystem);
    }

    /**
     * 添加钉钉链接通知
     *
     * @param type
     * @param content
     * @param users
     * @return
     */
    private void buildDingLinkNotice(NoticeRecordDTO notice, String type, String content, List<String> users) {
        final NoticeDingDTO toDing = new NoticeDingDTO();
        toDing.setMsgtype("link");
        toDing.setUsers(users);
        final Map<String, String> linkParams = Maps.newHashMap();
        linkParams.put("messageUrl", "eapp://pages/questionnaire/questionnaire");
        linkParams.put("picUrl", "@lALPDeRETJL6S3XMtMy0");
        linkParams.put("title", type);
        linkParams.put("text", content);
        toDing.setJsonBody(JsonUtils.pojoToJson(linkParams));
        notice.setDing(toDing);
    }

    /**
     * 添加钉钉链接通知
     *
     * @param type
     * @param content
     * @param users
     * @return
     */
    private void buildDingTextNotice(NoticeRecordDTO notice, String type, String content, List<String> users) {
        final NoticeDingDTO toDing = new NoticeDingDTO();
        toDing.setMsgtype("text");
        toDing.setUsers(users);
        final Map<String, String> linkParams = Maps.newHashMap();
        linkParams.put("content", content);
        toDing.setJsonBody(JsonUtils.pojoToJson(linkParams));
        notice.setDing(toDing);
    }

}
